package com.pshcp.patient.api;

import cn.hutool.core.date.DateUtil;
import com.external.pay.PayService;
import com.external.pay.domain.PayPackageDTO;
import com.framework.base.PageList;
import com.framework.base.ResultBuilder;
import com.framework.base.ResultDTO;
import com.framework.exception.BizException;
import com.framework.logaop.Log;
import com.framework.logaop.LogSourceEnum;
import com.framework.logaop.LogTypeEnum;
import com.framework.thread.ReqComHold;
import com.framework.tool.CommonTool;
import com.pshcp.common.enums.RegPayStatusEnum;
import com.pshcp.domain.dto.PatientOnlineOrderDTO;
import com.pshcp.domain.model.Doctor;
import com.pshcp.domain.model.Patient;
import com.pshcp.domain.model.PatientOnlineMedicalRecords;
import com.pshcp.domain.model.PatientOnlineOrder;
import com.pshcp.domain.model.PatientUser;
import com.pshcp.patient.business.OnlineOrderBusiness;
import com.pshcp.patient.domain.onlineorder.ao.OnlineConfirmAO;
import com.pshcp.patient.domain.onlineorder.ao.OnlineDetailAO;
import com.pshcp.patient.domain.onlineorder.ao.OnlineListAO;
import com.pshcp.patient.domain.onlineorder.ao.OnlineRefundAO;
import com.pshcp.patient.domain.onlineorder.ao.OnlineSuggestAO;
import com.pshcp.patient.domain.onlineorder.ao.OnlineToPayAO;
import com.pshcp.patient.domain.onlineorder.vo.OnlineOrderVO;
import com.pshcp.patient.domain.patientuser.ao.PatientFeedbackAO;
import com.pshcp.patient.tool.OnlineOrderTools;
import com.pshcp.patient.tool.PatientUserTools;
import com.pshcp.service.DoctorService;
import com.pshcp.service.FeedbackService;
import com.pshcp.service.PatientOnlineMedicalRecordsService;
import com.pshcp.service.PatientOnlineOrderService;
import com.pshcp.service.PatientService;
import com.pshcp.service.PatientUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Api(tags = {"患者端-在线咨询"})
@Slf4j
@RestController
@RequestMapping("/api/patient/onlineOrder")
public class OnlineOrderAPI {

    @Autowired
    private PatientOnlineOrderService onlineOrderService;

    @Autowired
    private PatientOnlineMedicalRecordsService medicalRecordsService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private OnlineOrderBusiness onlineOrderBusiness;

    @Autowired
    private PayService payService;

    @Autowired
    private PatientUserService patientUserService;

    @Autowired
    private FeedbackService feedbackService;

    @Value("${custom.patient.online-fee:0}")
    private BigDecimal onlineFee;

    @Value("${custom.patient.un-pay-timeout:15}")
    private Integer unPayTimeout;

    @ApiOperation("咨询单确认")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.SELECT, desc = "咨询单确认")
    @PostMapping("/confirm")
    public ResultDTO confirm(@Valid @RequestBody OnlineConfirmAO confirmAO) throws BizException {

        Doctor doctor = doctorService.findById(confirmAO.getDoctorId());
        CommonTool.checkObj(doctor, "10120001");

        Patient patient = patientService.findById(confirmAO.getPatientId());
        CommonTool.checkObj(patient, "10120002");

        doctor.setOnlineFee(onlineFee);
        Long onlineOrderId = onlineOrderBusiness.createOrder(confirmAO, doctor, patient);
        return ResultBuilder.success(onlineOrderId);
    }

    @ApiOperation("去支付")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.UPDATE, desc = "去支付")
    @PostMapping("/toPay")
    public ResultDTO<PayPackageDTO> toPay(@RequestBody OnlineToPayAO toPayAO) throws BizException {
        PatientOnlineOrder onlineOrder = onlineOrderService.findById(toPayAO.getOnlineOrderId());
        if(!RegPayStatusEnum.WAIT_PAY.getCode().equals(onlineOrder.getPayStatus())){
            return ResultBuilder.failure("10170008");
        }
        if(BigDecimal.ZERO.compareTo(onlineOrder.getPayFee()) >= 0){
            onlineOrderBusiness.enterOnlineOrder(onlineOrder);
            PayPackageDTO payPackageDTO = new PayPackageDTO();
            payPackageDTO.setSkipPay(true);
            return ResultBuilder.success(payPackageDTO);
        }
        PatientUser patientUser = patientUserService.findById(ReqComHold.getReqCom().getUserId());
        toPayAO.setOpenid(patientUser.getOpenid());

        PayPackageDTO payPackageDTO = payService.callPay(OnlineOrderTools.buildPayDTO(onlineOrder, toPayAO));
        return ResultBuilder.success(payPackageDTO);
    }

    @ApiOperation("咨询单详情")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.SELECT, desc = "咨询单详情")
    @PostMapping("/onlineDetail")
    public ResultDTO<OnlineOrderVO> regDetail(@RequestBody OnlineDetailAO detailAO) throws BizException {
        PatientOnlineOrder onlineOrder = onlineOrderService.findById(detailAO.getOnlineOrderId());
        CommonTool.checkObj(onlineOrder, "10170001");
        OnlineOrderVO onlineOrderVO = CommonTool.copyProperties(onlineOrder, OnlineOrderVO.class);
        onlineOrderVO.setExpireTime(DateUtil.offsetMinute(onlineOrderVO.getCreatedTime(), unPayTimeout));
        return ResultBuilder.success(onlineOrderVO);
    }

    @ApiOperation("咨询单列表")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.SELECT, desc = "咨询单列表")
    @PostMapping("/onlineList")
    public ResultDTO<PageList<OnlineOrderVO>> regList(@RequestBody OnlineListAO onlineListAO) {
        PatientOnlineOrderDTO orderDTO = OnlineOrderTools.buildListAO2DTO(onlineListAO);
        PageList<PatientOnlineOrder> pageList = onlineOrderService.list(orderDTO);
        PageList<OnlineOrderVO> voPageList = CommonTool.buildPageList(pageList, OnlineOrderVO.class);
        buildMedicalDesc(voPageList.getItems());
        return ResultBuilder.success(voPageList);
    }

    private void buildMedicalDesc(List<OnlineOrderVO> voList){
        if(CollectionUtils.isEmpty(voList)){
            return;
        }
        List<Long> onlineIds = voList.stream().map(v->v.getId()).collect(Collectors.toList());
        List<PatientOnlineMedicalRecords> medicalRecords = medicalRecordsService.findByOnlineOrderIds(onlineIds);
        Map<Long, String> idAndNameMap = medicalRecords.stream().collect(Collectors.toMap(mr-> mr.getPatientOnlineOrderId(), mr -> mr.getIllnessDescription()));
        voList.forEach(item -> {
            item.setMedicalDesc(idAndNameMap.get(item.getId()));
        });
    }

    @ApiOperation("咨询单删除")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.LOGIC_DEL, desc = "咨询单删除")
    @PostMapping("/del")
    public ResultDTO del(@RequestBody OnlineDetailAO detailAO) {
        onlineOrderService.delById(detailAO.getOnlineOrderId());
        return ResultBuilder.success();
    }

    @ApiOperation("咨询单退诊")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.UPDATE, desc = "咨询单退诊")
    @PostMapping("/refund")
    public ResultDTO refund(@RequestBody OnlineRefundAO refundAO) throws BizException {
        PatientOnlineOrder onlineOrder = onlineOrderService.findById(refundAO.getOnlineOrderId());

        if(!RegPayStatusEnum.PAY_OK.getCode().equals(onlineOrder.getPayStatus())){
            return ResultBuilder.failure("10170009");
        }
        onlineOrder.setCancelReason(refundAO.getRefundReason());
        onlineOrderBusiness.refundOnlineOrder(onlineOrder);
        return ResultBuilder.success();
    }

    @ApiOperation("意见反馈")
    @Log(source = LogSourceEnum.PATIENT_APP, type = LogTypeEnum.ADD, desc = "意见反馈")
    @PostMapping("/suggest")
    public ResultDTO suggest(@RequestBody OnlineSuggestAO onlineSuggestAO) {
        feedbackService.insert(OnlineOrderTools.buildOnlineSuggest(onlineSuggestAO));
        return ResultBuilder.success();
    }

}
